<!--
xiaozhi-message 消息处理节点
用于处理MCP消息的发送、接收和格式化
-->

<script type="text/javascript">
  RED.nodes.registerType('xiaozhi-message', {
    category: '小智MCP',
    color: '#DDA0DD',
    defaults: {
      name: { value: '' },
      xiaozhi: { value: '', type: 'xiaozhi-config', required: true },
      messageMode: { value: 'send' },
      messageType: { value: 'notification' },
      method: { value: '' },
      params: { value: '{}' },
      paramsSource: { value: 'configured' },
      outputFormat: { value: 'payload' },
      filterIncoming: { value: true },
      methodFilter: { value: '' },
      enableLogging: { value: true }
    },
    inputs: function() {
      return this.messageMode === 'receive' ? 0 : 1;
    },
    outputs: function() {
      return this.messageMode === 'bidirectional' ? 2 : 1;
    },
    outputLabels: function() {
      if (this.messageMode === 'bidirectional') {
        return ['发送确认', '接收消息'];
      }
      return this.messageMode === 'receive' ? '接收消息' : '发送确认';
    },
    icon: 'font-awesome/fa-exchange',
    label: function() {
      if (this.name) return this.name;
      if (this.method) return `消息: ${this.method}`;
      return '消息处理';
    },
    paletteLabel: '消息处理',
    oneditprepare: function() {
      var node = this;
      
      // 初始化参数编辑器
      var paramsEditor = RED.editor.createEditor({
        id: 'node-input-params-editor',
        mode: 'ace/mode/json',
        value: node.params || '{}'
      });

      // 消息模式变化处理
      $('#node-input-messageMode').on('change', function() {
        var mode = $(this).val();
        var sendOptions = $('#send-options');
        var receiveOptions = $('#receive-options');
        
        if (mode === 'send') {
          sendOptions.show();
          receiveOptions.hide();
        } else if (mode === 'receive') {
          sendOptions.hide();
          receiveOptions.show();
        } else {
          sendOptions.show();
          receiveOptions.show();
        }
      });

      // 参数来源变化处理
      $('#node-input-paramsSource').on('change', function() {
        var source = $(this).val();
        var paramsContainer = $('#params-editor-container');
        paramsContainer.toggle(source === 'configured');
      });

      // JSON参数验证
      var validateParams = function() {
        try {
          JSON.parse(paramsEditor.getValue());
          $('#params-error').hide();
          $('#params-valid').show();
          return true;
        } catch (e) {
          $('#params-error').text('JSON格式错误: ' + e.message).show();
          $('#params-valid').hide();
          return false;
        }
      };

      paramsEditor.on('change', function() {
        setTimeout(validateParams, 500);
      });

      // 预定义模板
      $('#method-template').on('change', function() {
        var template = $(this).val();
        var templates = {
          'ping': { method: 'ping', params: {} },
          'tools/list': { method: 'tools/list', params: {} },
          'tools/call': { method: 'tools/call', params: { name: 'tool_name', arguments: {} }}
        };
        if (template && templates[template]) {
          $('#node-input-method').val(templates[template].method);
          paramsEditor.setValue(JSON.stringify(templates[template].params, null, 2));
        }
      });

      // 测试发送
      $('#test-send').on('click', function() {
        if (!node.id) {
          RED.notify('请先保存节点配置', 'warn');
          return;
        }
        var method = $('#node-input-method').val();
        var params = {};
        try {
          params = JSON.parse(paramsEditor.getValue());
        } catch (e) {
          RED.notify('参数JSON格式错误', 'error');
          return;
        }

        $.ajax({
          url: 'xiaozhi-message/' + node.id + '/test',
          method: 'POST',
          contentType: 'application/json',
          data: JSON.stringify({ method, params }),
          success: function(data) {
            RED.notify(data.success ? '消息发送成功' : '发送失败: ' + data.error, 
                      data.success ? 'success' : 'error');
          },
          error: function() {
            RED.notify('发送失败', 'error');
          }
        });
      });

      // 初始化
      setTimeout(function() {
        $('#node-input-messageMode').trigger('change');
        $('#node-input-paramsSource').trigger('change');
        validateParams();
      }, 100);
    },
    oneditsave: function() {
      var paramsEditor = RED.editor.getEditor('node-input-params-editor');
      if (paramsEditor) {
        this.params = paramsEditor.getValue();
      }
    },
    oneditcancel: function() {
      var paramsEditor = RED.editor.getEditor('node-input-params-editor');
      if (paramsEditor) {
        paramsEditor.destroy();
      }
    }
  });
</script>

<script type="text/html" data-template-name="xiaozhi-message">
  <div class="form-row">
    <label for="node-input-name"><i class="fa fa-tag"></i> 节点名称</label>
    <input type="text" id="node-input-name" placeholder="可选的节点名称">
  </div>

  <div class="form-row">
    <label for="node-input-xiaozhi"><i class="fa fa-plug"></i> 小智配置</label>
    <input type="text" id="node-input-xiaozhi">
  </div>

  <div class="form-row">
    <label for="node-input-messageMode"><i class="fa fa-exchange"></i> 消息模式</label>
    <select id="node-input-messageMode">
      <option value="send">仅发送</option>
      <option value="receive">仅接收</option>
      <option value="bidirectional">双向处理</option>
    </select>
  </div>

  <div id="send-options">
    <div class="form-row">
      <label for="node-input-messageType"><i class="fa fa-envelope"></i> 消息类型</label>
      <select id="node-input-messageType">
        <option value="notification">通知</option>
        <option value="request">请求</option>
        <option value="response">响应</option>
      </select>
    </div>

    <div class="form-row">
      <label for="node-input-method"><i class="fa fa-code"></i> 方法名称</label>
      <input type="text" id="node-input-method" placeholder="ping">
      <select id="method-template" style="width: 120px; margin-left: 10px;">
        <option value="">模板...</option>
        <option value="ping">ping</option>
        <option value="tools/list">tools/list</option>
        <option value="tools/call">tools/call</option>
      </select>
    </div>

    <div class="form-row">
      <label for="node-input-paramsSource"><i class="fa fa-code"></i> 参数来源</label>
      <select id="node-input-paramsSource">
        <option value="configured">配置的参数</option>
        <option value="msg">msg.payload</option>
        <option value="msg.params">msg.params</option>
        <option value="flow">Flow上下文</option>
        <option value="global">Global上下文</option>
      </select>
    </div>

    <div id="params-editor-container">
      <div class="form-row">
        <label for="node-input-params-editor">消息参数</label>
        <div style="height: 150px;" class="node-text-editor" id="node-input-params-editor"></div>
        <div id="params-valid" style="display:none; color: green;">
          <i class="fa fa-check"></i> 参数格式正确
        </div>
        <div id="params-error" style="display:none; color: red;">
          <i class="fa fa-exclamation-triangle"></i> <span></span>
        </div>
      </div>
    </div>
  </div>

  <div id="receive-options" style="display:none;">
    <div class="form-row">
      <label>&nbsp;</label>
      <input type="checkbox" id="node-input-filterIncoming" style="width:auto;">
      <label for="node-input-filterIncoming" style="width:70%;">启用消息过滤</label>
    </div>

    <div class="form-row">
      <label for="node-input-methodFilter"><i class="fa fa-filter"></i> 方法过滤器</label>
      <input type="text" id="node-input-methodFilter" placeholder="ping,tools/*">
    </div>
  </div>

  <div class="form-row">
    <label for="node-input-outputFormat"><i class="fa fa-share"></i> 输出格式</label>
    <select id="node-input-outputFormat">
      <option value="payload">提取数据</option>
      <option value="full">完整对象</option>
      <option value="jsonrpc">原始消息</option>
    </select>
  </div>

  <div class="form-row">
    <label>&nbsp;</label>
    <input type="checkbox" id="node-input-enableLogging" style="width:auto;">
    <label for="node-input-enableLogging" style="width:70%;">启用消息日志记录</label>
  </div>

  <div class="form-row">
    <label>&nbsp;</label>
    <button type="button" id="test-send" class="red-ui-button">
      <i class="fa fa-paper-plane"></i> 测试发送
    </button>
  </div>
</script>

<script type="text/html" data-help-name="xiaozhi-message">
  <p>xiaozhi-message节点用于处理MCP消息的发送、接收和格式化，支持JSON-RPC 2.0协议。</p>

  <h3>配置说明</h3>
  <dl class="message-properties">
    <dt>消息模式</dt>
    <dd>仅发送：只发送消息到MCP服务器</dd>
    <dd>仅接收：只接收来自MCP服务器的消息</dd>
    <dd>双向处理：可发送和接收消息</dd>

    <dt>消息类型</dt>
    <dd>通知：单向发送，无需响应</dd>
    <dd>请求：需要响应，包含消息ID</dd>
    <dd>响应：回复其他请求</dd>

    <dt>参数来源</dt>
    <dd>配置的参数：使用下方编辑器中的固定参数</dd>
    <dd>msg.payload：使用输入消息的payload</dd>
    <dd>其他：使用指定的消息属性或上下文</dd>
  </dl>

  <h3>支持的MCP方法</h3>
  <ul>
    <li>ping - 心跳检测</li>
    <li>initialize - 初始化连接</li>
    <li>tools/list - 获取工具列表</li>
    <li>tools/call - 调用工具</li>
    <li>自定义方法</li>
  </ul>

  <h3>使用示例</h3>
  <p><strong>发送ping消息：</strong></p>
  <ol>
    <li>消息模式：仅发送</li>
    <li>消息类型：通知</li>
    <li>方法名称：ping</li>
    <li>参数：{}</li>
  </ol>

  <p><strong>接收工具调用：</strong></p>
  <ol>
    <li>消息模式：仅接收</li>
    <li>启用消息过滤</li>
    <li>方法过滤器：tools/*</li>
  </ol>
</script>